#include "tech_hsc.h"
#include "DB0.h"
#include "xmzTypeDefine.h"
#include "SystemType.h"
#include <stdint.h>
/*--------------------- 6路计数器配置表 ------------*/
HSCConf hsc_conf[] = {
    // TIM2_CH2 @ PB3
    {.TIMx           = TIM2,
     .Channel        = TIM_CHANNEL_2,
     .GPIO_Port      = GPIOB,
     .GPIO_Pin       = GPIO_PIN_3,
     .GPIO_AF        = GPIO_AF1_TIM2,
     .htim           = {0},
     .overflow_count = 0,
     .direction      = 0,
     .initial_value  = 0,
     .active         = 0},
    // TIM3_CH1 @ PB4
    {.TIMx           = TIM3,
     .Channel        = TIM_CHANNEL_1,
     .GPIO_Port      = GPIOB,
     .GPIO_Pin       = GPIO_PIN_4,
     .GPIO_AF        = GPIO_AF2_TIM3,
     .htim           = {0},
     .overflow_count = 0,
     .direction      = 0,
     .initial_value  = 0,
     .active         = 0},
    // TIM4_CH1 @ PB6
    {.TIMx           = TIM4,
     .Channel        = TIM_CHANNEL_1,
     .GPIO_Port      = GPIOB,
     .GPIO_Pin       = GPIO_PIN_6,
     .GPIO_AF        = GPIO_AF2_TIM4,
     .htim           = {0},
     .overflow_count = 0,
     .direction      = 0,
     .initial_value  = 0,
     .active         = 0},
    // TIM9_CH1 @ PE5
    {.TIMx           = TIM9,
     .Channel        = TIM_CHANNEL_1,
     .GPIO_Port      = GPIOE,
     .GPIO_Pin       = GPIO_PIN_5,
     .GPIO_AF        = GPIO_AF3_TIM9,
     .htim           = {0},
     .overflow_count = 0,
     .direction      = 0,
     .initial_value  = 0,
     .active         = 0},
    // TIM5_CH2 @ PA1
    {.TIMx           = TIM5,
     .Channel        = TIM_CHANNEL_2,
     .GPIO_Port      = GPIOA,
     .GPIO_Pin       = GPIO_PIN_1,
     .GPIO_AF        = GPIO_AF2_TIM5,
     .htim           = {0},
     .overflow_count = 0,
     .direction      = 0,
     .initial_value  = 0,
     .active         = 0},
    // TIM12_CH1 @ PB14
    {.TIMx           = TIM12,
     .Channel        = TIM_CHANNEL_1,
     .GPIO_Port      = GPIOB,
     .GPIO_Pin       = GPIO_PIN_14,
     .GPIO_AF        = GPIO_AF9_TIM12,
     .htim           = {0},
     .overflow_count = 0,
     .direction      = 0,
     .initial_value  = 0,
     .active         = 0}};

/*--------------------- 定时器初始化 ---------------*/
void static TIM_HSC_Init(HSCConf* config) {
  // 使能时钟
  if(config->TIMx == TIM2)
    __HAL_RCC_TIM2_CLK_ENABLE();
  else if(config->TIMx == TIM3)
    __HAL_RCC_TIM3_CLK_ENABLE();
  else if(config->TIMx == TIM4)
    __HAL_RCC_TIM4_CLK_ENABLE();
  else if(config->TIMx == TIM5)
    __HAL_RCC_TIM5_CLK_ENABLE();
  else if(config->TIMx == TIM9)
    __HAL_RCC_TIM9_CLK_ENABLE();
  else if(config->TIMx == TIM12)
    __HAL_RCC_TIM12_CLK_ENABLE();

  // GPIO初始化
  GPIO_InitTypeDef GPIO_InitStruct = {.Pin       = config->GPIO_Pin,
                                      .Mode      = GPIO_MODE_AF_PP,
                                      .Pull      = GPIO_NOPULL,
                                      .Speed     = GPIO_SPEED_FREQ_VERY_HIGH,
                                      .Alternate = config->GPIO_AF};
  HAL_GPIO_Init(config->GPIO_Port, &GPIO_InitStruct);

  // 定时器基础配置
  config->htim.Instance       = config->TIMx;
  config->htim.Init.Prescaler = 0; // 无分频
  // 根据direction设置计数模式
  config->htim.Init.CounterMode   = TIM_COUNTERMODE_UP;
  config->htim.Init.Period        = 0xFFFF; // 65535
  config->htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  HAL_TIM_IC_Init(&config->htim);

  // 配置外部时钟模式
  TIM_SlaveConfigTypeDef sSlaveConfig = {.SlaveMode    = TIM_SLAVEMODE_EXTERNAL1,
                                         .InputTrigger = TIM_TS_TI2FP2, // 根据通道调整触发源

                                         .TriggerPolarity  = TIM_TRIGGERPOLARITY_FALLING,
                                         .TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1,
                                         .TriggerFilter    = 0x04};
  if(config->Channel == TIM_CHANNEL_1)
    sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;
  else if(config->Channel == TIM_CHANNEL_2)
    sSlaveConfig.InputTrigger = TIM_TS_TI2FP2;

  HAL_TIM_SlaveConfigSynchro(&config->htim, &sSlaveConfig);

  // 设置中断优先级并使能 NVIC
  IRQn_Type irq;
  if(config->TIMx == TIM2)
    irq = TIM2_IRQn;
  else if(config->TIMx == TIM3)
    irq = TIM3_IRQn;
  else if(config->TIMx == TIM4)
    irq = TIM4_IRQn;
  else if(config->TIMx == TIM5)
    irq = TIM5_IRQn;
  else if(config->TIMx == TIM9)
    irq = TIM1_BRK_TIM9_IRQn;
  else if(config->TIMx == TIM12)
    irq = TIM8_BRK_TIM12_IRQn;

  HAL_NVIC_SetPriority(irq, 1, 3); // 设置中断优先级，抢占优先级 1，子优先级 3
  HAL_NVIC_EnableIRQ(irq);

  __HAL_TIM_SET_COUNTER(&config->htim, 0);              /* 计数器清零 */
  __HAL_TIM_CLEAR_FLAG(&config->htim, TIM_FLAG_UPDATE); /* 清除更新中断标志 */
  // HAL_TIM_Base_Start(&config->htim);  // 启动定时器
  HAL_TIM_IC_Start(&config->htim, config->Channel);  /* 开始捕获TIMx的通道y */
  __HAL_TIM_ENABLE_IT(&config->htim, TIM_IT_UPDATE); /* 使能更新中断 */
}

/*--------------------- 初始化开启的所有计数器 -----------*/
void All_HSC_Init(void) {
  for(uint8_t i = 0; i < 6; i++) {
    if(hsc_conf[i].active) {
      TIM_HSC_Init(&hsc_conf[i]);
      g_DB0_t->HSC[i] = hsc_conf[i].initial_value;
      // hsc_conf[i].overflow_count = 0;
    }
  }
}

/**
 * @brief 重置初始值
 *
 * @param ch 通道号
 * @param cv 新初始值
 */
static void Reset_HSC_CV(enum HSC_CH ch, int32_t cv) {
  HSCConf* counter        = &hsc_conf[ch];
  counter->initial_value  = cv;
  counter->overflow_count = 0;
}
/**
 * @brief 重置方向
 *
 * @param ch 通道号
 * @param dir 0 正转 1 倒转
 */
static void Reset_HSC_DIR(enum HSC_CH ch, int8_t dir) {
  HSCConf* counter   = &hsc_conf[ch];
  counter->direction = dir;
}
/**
 * @brief 通用高速计数器中断处理函数
 *
 * @param ch 计数器通道号HSC_1 ~ HSC_6
 */
static void HSC_IRQHandler(enum HSC_CH ch) {
  if(__HAL_TIM_GET_FLAG(&hsc_conf[ch].htim, TIM_FLAG_UPDATE) != RESET) {

    hsc_conf[ch].overflow_count++;
  }
  __HAL_TIM_CLEAR_IT(&hsc_conf[ch].htim, TIM_IT_UPDATE);
}
/**
 * @brief TIM2 中断处理函数
 * 清除 TIM2 的更新中断标志位，并增加对应计数器的溢出计数
 */
void TIM2_IRQHandler(void) {
  HSC_IRQHandler(HSC_1);
}
static uint32_t getHSC(enum HSC_CH ch) {
  // FIXME: 当前双向计数实现有问题：
  // 1. 未在中断中区分向上溢出与向下溢出（通过 TIMx->CR1 DIR 位判断）。
  // 2. 溢出计数 overflow_count 与 16 位定时器值直接拼接可能导致符号扩展错误。
  // 建议：
  //   - 在中断中根据方向更新 overflow_count（++ 或 --）
  //   - 在此处统一组合为 int32_t 计数值
  uint32_t counter = __HAL_TIM_GET_COUNTER(&hsc_conf[ch].htim); // 先用无符号
  uint32_t total_count;

  if(hsc_conf[ch].direction == 0) {
    // 加计数
    total_count = hsc_conf[ch].initial_value + (hsc_conf[ch].overflow_count * 0x10000) + counter;
  } else {
    // 减计数
    total_count = hsc_conf[ch].initial_value - (hsc_conf[ch].overflow_count * 0x10000) - counter;
  }
  return total_count;
}
void updataHSC(void) {
  for(int i = 0; i < 6; i++) {
    if(hsc_conf[i].active == 1)
      g_DB0_t->HSC[i] = getHSC(i);
  }
}
/**
 * @brief TIM3 中断处理函数
 * 清除 TIM3 的更新中断标志位，并增加对应计数器的溢出计数
 */
void TIM3_IRQHandler(void) {
  HSC_IRQHandler(HSC_2);
}

/**
 * @brief TIM4 中断处理函数
 * 清除 TIM4 的更新中断标志位，并增加对应计数器的溢出计数
 */
void TIM4_IRQHandler(void) {
  HSC_IRQHandler(HSC_3);
}

/**
 * @brief TIM5 中断处理函数
 * 清除 TIM5 的更新中断标志位，并增加对应计数器的溢出计数
 */
void TIM1_BRK_TIM9_IRQHandler(void) {
  HSC_IRQHandler(HSC_4);
}

/**
 * @brief TIM1_BRK_TIM9 中断处理函数
 * 清除 TIM9 的更新中断标志位，并增加对应计数器的溢出计数
 */
void TIM5_IRQHandler(void) {
  HSC_IRQHandler(HSC_5);
}

/**
 * @brief TIM8_BRK_TIM12 中断处理函数
 * 清除 TIM12 的更新中断标志位，并增加对应计数器的溢出计数
 */
void TIM8_BRK_TIM12_IRQHandler(void) {
  HSC_IRQHandler(HSC_6);
}

/**
 * @brief 开启某个高速计数器
 *
 * @param ch 通道号：HSC_1 ~ HSC_6
 * @param direction 方向：1加，-1减
 * @param inittial_value 设定值
 * @return Bool
 */

Bool StartHSCCapture(enum HSC_CH ch, int8_t direction, int32_t inittial_value) {
  if(hsc_conf[ch].active == 0) {
    hsc_conf[ch].active        = 1;
    hsc_conf[ch].direction     = (direction == 1) ? 0 : 1; // 1为加计数，-1为减计数
    hsc_conf[ch].initial_value = inittial_value;
    return True;
  } else {
    return False;
  }
}
Bool CTRL_HSC_C(Bool en, CTRL_HSC_S* instance) {
  if(en == False || instance == NULL) {
    return False;
  }
  if(instance->hsc < HSC_1 || instance->hsc > HSC_6) {
    instance->status = HSC_STATUS_ERR_CH_NUM;
    return False;
  }
  if(hsc_conf[instance->hsc].active == 0) {
    instance->status = HSC_STATUS_ERR_NOT_ON; // 硬件未开启
    return False;
  }
  if(instance->cv == True)
    Reset_HSC_CV(instance->hsc, instance->new_cv);
  if(instance->dir == True)
    Reset_HSC_DIR(instance->hsc, instance->new_dir == 1 ? 0 : 1);
  return True;
}

void CTRL_HSC_S_pack(CTRL_HSC_S* s_ptr, uint8_t* buffer, size_t buffer_size, uint16_t byte_offset)
{
    return;
}

void CTRL_HSC_S_unpack(CTRL_HSC_S* s_ptr, uint8_t* buffer, size_t buffer_size, uint16_t byte_offset)
{
    return;
}


